<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>
        function* helloWorldGenerator() {
            yield 'hello';
            yield 'world';
            return 'ending';
        }
        // 只有调用next方法才会遍历下一个内部状态，所以其实提供了一种可以暂停执行的函数。
        // yield表达式就是暂停标志

        var hw = helloWorldGenerator();

        console.log(hw.next());
        // { value: 'hello', done: false }

        console.log(hw.next());
        // { value: 'world', done: false }

        console.log(hw.next());
        // { value: 'ending', done: true }

        console.log(hw.next());
        // { value: undefined, done: true }

        // （1）遇到yield表达式，就暂停执行后面的操作，
        // 并将紧跟在yield后面的那个表达式的值，作为返回的对象的value属性值
        // （2）下一次调用next方法时，再继续往下执行，直到遇到下一个yield表达式


        // 由于 Generator 函数就是遍历器生成函数，
        // 因此可以把 Generator 赋值给对象的Symbol.iterator属性，从而使得该对象具有 Iterator 接口
        var myIterable = {};
        myIterable[Symbol.iterator] = function* () {
            yield 1;
            yield 2;
            yield 3;
        };
        console.log([...myIterable]); // [1, 2, 3]


        // 利用 Generator 函数和for...of循环，实现斐波那契数列
        function* fibonacci() {
            let [prev, curr] = [0, 1];
            for (;;) {
                yield curr;
                [prev, curr] = [curr, prev + curr];
            }
        }

        for (let n of fibonacci()) {
            if (n > 1000) break;
            console.log(n);
        }


        // Generator 函数返回的遍历器对象，还有一个return方法，
        // 可以返回给定的值，并且终结遍历 Generator 函数
        function* gen() {
            yield 1;
            yield 2;
            yield 3;
        }
        var g = gen();

        g.next()        // { value: 1, done: false }
        g.return('foo') // { value: "foo", done: true }
        g.next()        // { value: undefined, done: true }


        // Generator 函数内部还可以部署错误处理代码，捕获函数体外抛出的错误
        function* gen(x){
            try {
                var y = yield x + 2;
            } catch (e){
                console.log(e);
            }
            return y;
        }

        let g1 = gen(1);
        console.log(g1.next());
        g.throw('出错了');
        // 出错了

    </script>

</head>
<body>

</body>
</html>